#include "RadianMainEditorController.h"
#include "RadianEditorMathHelper.h"
#include "RadianRenderWnd.h"
#include "RadianAxisDrawer.h"


#include <QWidget>
#include <QtGui/QApplication>
#include "OgreSceneNode.h"
#include "OgreMovableObject.h"
#include "OgreSceneManager.h"
#include "OgreRenderWindow.h"

//--------------------------------------------------------------------------
RadianMainEditorController::RadianMainEditorController(Ogre::Camera* camera, QWidget* parentWidget,RadianRenderWnd* parentRenderWindow)
	:RadianEditorController(camera, parentWidget, parentRenderWindow)
	,mIsFlying(false)
	,mIsTargeting(false)
	,mLastLookAtPosition(0,0,0)
{
	mAxisDrawer = new RadianAxisDrawer(this);
	mAxisDrawer->InitializeAxis();
}
//--------------------------------------------------------------------------
RadianMainEditorController::~RadianMainEditorController()
{
	mSelectedNodes.clear();
	mSelectedNode = NULL;	
}
//--------------------------------------------------------------------------
void RadianMainEditorController::OnKeyPress( QKeyEvent* evt )
{
	switch(evt->key())
	{
	case Qt::Key_F:
		{
			if(mSelectedNode)
			{
				FocusTo(mSelectedNode->_getWorldAABB());
			}

			else if(mSelectedNodes.size())
			{
				FocusTo(RadianEditorMathHelper::GetMergedAABB(mSelectedNodes));		
			}
			break;
		}
	case Qt::Key_W:
		{
			mEditMode = Edit_Move;
			break;
		}
	case Qt::Key_S:
		{
			mEditMode = Edit_Scale;
			break;
		}
	case Qt::Key_R:
		{
			mEditMode = Edit_Rotate;
			break;
		}
	case Qt::Key_Escape:
		{
			mEditMode = Edit_None;
			break;
		}
	}
	RadianEditorController::OnKeyPress(evt);
}
//--------------------------------------------------------------------------
void RadianMainEditorController::OnKeyRelease( QKeyEvent* evt )
{
	RadianEditorController::OnKeyRelease(evt);
}
//--------------------------------------------------------------------------
void RadianMainEditorController::OnMouseMove( QMouseEvent* evt )
{
	if(mAxisDrawer->OnMouseMove(evt))
		return;

	RadianEditorController::OnMouseMove(evt);
}
//--------------------------------------------------------------------------
void RadianMainEditorController::OnMousePress(QMouseEvent* evt )
{
	
	RadianEditorController::OnMousePress(evt);

	if(mAxisDrawer->OnMouseDown(evt))
		return;


	if(evt->button() == Qt::LeftButton)
	{
		if(QApplication::keyboardModifiers() == Qt::ControlModifier)
		{
			// multiple-selection.

			// do a itersection.
			Ogre::MovableObject* targetMovableObj = NULL;
			Math::Vector3 outPos;
			Ogre::Vector2 screenPos = RadianEditorMathHelper::GetScreenPos(evt->posF(), mParentWidget->size());
			if(RadianEditorMathHelper::DoSceneQuery(mTargetCamera,mParentRenderWindow->GetSceneMgr(),screenPos,Ogre::StringUtil::BLANK,targetMovableObj,outPos))
			{
				if(targetMovableObj && targetMovableObj->getParentSceneNode())
				{
					if(targetMovableObj->getParentSceneNode() != mAxisDrawer->GetAxisNode())
					{
						//skip the axis node.
						mSelectedNode = NULL;
						targetMovableObj->getParentSceneNode()->showBoundingBox(true);
						mSelectedNodes.push_back(targetMovableObj->getParentSceneNode());
					}
				}
			}
		}

		else
		{
			// single-selection.
			Ogre::MovableObject* targetMovableObj = NULL;
			Math::Vector3 outPos;
			Ogre::Vector2 screenPos = RadianEditorMathHelper::GetScreenPos(evt->posF(), mParentWidget->size());
			if(RadianEditorMathHelper::DoSceneQuery(mTargetCamera,mParentRenderWindow->GetSceneMgr(),screenPos,Ogre::StringUtil::BLANK,targetMovableObj,outPos))
			{
				if(targetMovableObj && targetMovableObj->getParentSceneNode())
				{
					if(targetMovableObj->getParentSceneNode() != mAxisDrawer->GetAxisNode())
					{
						UnSelectAllObjects();
						mSelectedNode = targetMovableObj->getParentSceneNode();
						mSelectedNode->showBoundingBox(true);
						mSelectedNodes.clear();
					}
				}
			}
		}
	}
}
//--------------------------------------------------------------------------
void RadianMainEditorController::OnMouseRelease( QMouseEvent* evt )
{
	mAxisDrawer->OnMouseUp(evt);
	
	RadianEditorController::OnMouseRelease(evt);
}
//--------------------------------------------------------------------------
void RadianMainEditorController::OnMouseDoublePress( QMouseEvent* evt )
{
	RadianEditorController::OnMouseDoublePress(evt);
}
//--------------------------------------------------------------------------
void RadianMainEditorController::OnMouseWheel( QWheelEvent* evt )
{
	RadianEditorController::OnMouseWheel(evt);
}
//--------------------------------------------------------------------------
bool RadianMainEditorController::eventFilter( QObject *target, QEvent *event )
{
	return RadianEditorController::eventFilter(target,event);
}
//--------------------------------------------------------------------------
void RadianMainEditorController::UnSelectAllObjects()
{
	if(mParentRenderWindow && mParentRenderWindow->GetSceneMgr())
	{
		RecursionSelectAllChildsNode(mParentRenderWindow->GetSceneMgr()->getRootSceneNode(),false);
	}
}
//--------------------------------------------------------------------------
void RadianMainEditorController::RecursionSelectAllChildsNode(Ogre::SceneNode* sceneNode,bool isSelected)
{
	if(!sceneNode)
		return;

	Ogre::Node::ChildNodeIterator subNodeIt = sceneNode->getChildIterator();
	while(subNodeIt.hasMoreElements())
	{
		Ogre::SceneNode* sceneNode = static_cast<Ogre::SceneNode*>(subNodeIt.getNext());
		sceneNode->showBoundingBox(isSelected);
		RecursionSelectAllChildsNode(sceneNode, isSelected);
	}
}
//--------------------------------------------------------------------------
void RadianMainEditorController::Update(float timeElapsed)
{	
	mAxisDrawer->UpdateMousePosition(mParentWidget->mapFromGlobal(QCursor::pos()));
	mAxisDrawer->Update();
	RadianEditorController::Update(timeElapsed);
}	
//--------------------------------------------------------------------------
void RadianMainEditorController::FocusTo(const Math::AxisAlignedBox& aabb)
{
	if(aabb.isNull())
		return;

	Ogre::Real FullTimeMod = 200.0f;
	Ogre::Real timeElapesd = FullTimeMod;

	Math::Vector3 targetPosition = Math::Vector3(aabb.getCenter().x
												 , aabb.getCenter().y + aabb.getSize().y == 0 ? 100 : aabb.getMaximum().y
												 , aabb.getCenter().y + aabb.getSize().z == 0 ? 100 : aabb.getMaximum().z);


	Math::Vector3 targetLook = aabb.getCenter();


	Math::Vector3 positionDiff = targetPosition - mTargetCamera->getPosition();
	Math::Vector3 oldLookAt = mTargetCamera->getPosition() + mTargetCamera->getDirection() * positionDiff.length();
	Math::Vector3 lookAtDiff = targetLook - oldLookAt;

	if(positionDiff.length() < 5)
	{
		timeElapesd = FullTimeMod = 5;
		for(Ogre::Real i = 0; i < FullTimeMod; i++)
		{
			mTargetCamera->setPosition(mTargetCamera->getPosition() + positionDiff / FullTimeMod);
			//mTargetCamera->lookAt(oldLookAt + lookAtDiff / FullTimeMod);
			mTargetCamera->lookAt(targetLook);
			mParentRenderWindow->GetRenderWindow()->update(true);
		}
		return;
	}

	for(Ogre::Real i = 0; i < FullTimeMod; i++)
	{
		mTargetCamera->setPosition(mTargetCamera->getPosition() + positionDiff / FullTimeMod);
		//mTargetCamera->lookAt(oldLookAt + lookAtDiff / FullTimeMod);
		mTargetCamera->lookAt(targetLook);
		mParentRenderWindow->GetRenderWindow()->update(true);
	}
}
//--------------------------------------------------------------------------
